﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using Affinity.Flux;
using Affinity.Synthesis;

namespace UserInterface
{
    public class DemoViewModel : NotifyPropertyChangedBase
    {
        #region Time

        [Inlet(Contracts.Time.CurrentTime, InletFlags.ReceiveOnUIThread)]
        public DateTime CurrentTime
        {
            get { return _currentTime; }
            set
            {
                if (value == _currentTime) return;
                _currentTime = value;
                RaisePropertyChanged("CurrentTime");
            }
        }
        private DateTime _currentTime;

        public string CurrentSecondType
        {
            get { return this.BindLambda("CurrentSecondType", () => CurrentTime.Second % 2 == 0 ? "Current second is even" : "Current second is odd"); }
        }

        #endregion

        #region Alarms

        [Inlet(Contracts.Time.AlarmAdded, InletFlags.ReceiveOnUIThread)]
        public void OnAlarmAdded(DateTime alarmTime)
        {
            MessageBox.Show("Alarm added for " + alarmTime);
        }

        [Inlet(Contracts.Time.AlarmFired, InletFlags.ReceiveOnUIThread)]
        public void Alarm(string message)
        {
            MessageBox.Show(message);
        }
        
        public ICommand AddAlarmCommand
        {
            get { return _addAlarmCommand ?? (_addAlarmCommand = new SimpleCommand(RaiseAddAlarm)); }
        }
        private ICommand _addAlarmCommand;

        [Outlet(Contracts.Time.AddAlarm)]
        public event Action<DateTime> AddAlarm;

        private void RaiseAddAlarm(object timeObject)
        {
            if (timeObject == null) return;
            DateTime time = (DateTime)timeObject;

            var addAlarm = AddAlarm;
            if (addAlarm != null) addAlarm(new DateTime(time.Year, time.Month, time.Day, time.Hour, time.Minute, 0));
        }

        public TimeSpan AlarmTimePickerStartTime 
        {
            get 
            { 
                return this.BindLambda("AlarmTimePickerStartTime", () => 
                    new TimeSpan(
                        CurrentTime.Hour, 
                        CurrentTime.Minute + 1,
                        0)); 
            }
        }

        #endregion

        #region Text Items

        public ICommand AddTextItemCommand
        {
            get { return _addTextItemCommand ?? (_addTextItemCommand = new SimpleCommand(arg => _textItems.Add(new TextItemViewModel()))); }
        }
        private ICommand _addTextItemCommand;

        public IEnumerable<TextItemViewModel> ItemsContainingLetterA
        {
            get 
            { 
                return this.BindLambda("ItemsContainingLetterA", () => 

                    from textItem in _textItems
                    where textItem.Text != null && textItem.Text.ToLower().Contains("a")
                    select textItem); 
            }
        }
        
        public string ItemsContainingLetterAAsString
        {
            get 
            {
                return this.BindLambda("ItemsContainingLetterAAsString", () => 
                    string.Join(", ", ItemsContainingLetterA.Select(item => item.Text))); 
            }
        }

        public string ItemsContainingLetterAAsStringAlt
        {
            get 
            {
                return this.BindLambda("ItemsContainingLetterAAsStringAlt", () => 
                    string.Join(", ", ItemsContainingLetterA.Select(GetItemText))); 
            }
        }

        private string GetItemText(TextItemViewModel item)
        {
            return item.Text;
        }

        [Component]
        public IEnumerable<TextItemViewModel> TextItems
        {
            get { return _textItems; }
        }

        private readonly ObservableCollection<TextItemViewModel> _textItems = new ObservableCollection<TextItemViewModel>(); 

        public int NumberOfTextItemsContainingLetterA
        {
            get { return this.BindLambda("NumberOfTextItemsContainingLetterA", () => ItemsContainingLetterA.Count()); }
        }

        #endregion

        #region Child ViewModels

        [Component]
        public DemoAltViewModel Alt 
        {
            get { return _alt; }
        }
        private readonly DemoAltViewModel _alt = new DemoAltViewModel();

        [Component]
        public DemoAlt2ViewModel Alt2
        {
            get { return _alt2; }
        }
        private readonly DemoAlt2ViewModel _alt2 = new DemoAlt2ViewModel();

        #endregion
    }
}
